# uncompyle6 version 3.2.3
# Python bytecode 3.6 (3379)
# Decompiled from: Python 3.6.8 |Anaconda custom (64-bit)| (default, Feb 21 2019, 18:30:04) [MSC v.1916 64 bit (AMD64)]
# Embedded file name: site-packages\gevent\signal.py
"""
Cooperative implementation of special cases of :func:`signal.signal`.

This module is designed to work with libev's child watchers, as used
by default in :func:`gevent.os.fork` Note that each ``SIGCHLD`` handler
will be run in a new greenlet when the signal is delivered (just like
:class:`gevent.hub.signal`)

The implementations in this module are only monkey patched if
:func:`gevent.os.waitpid` is being used (the default) and if
:const:`signal.SIGCHLD` is available; see :func:`gevent.os.fork` for
information on configuring this not to be the case for advanced uses.

.. versionadded:: 1.1b4
"""
from __future__ import absolute_import
from gevent._util import _NONE as _INITIAL
from gevent._util import copy_globals
import signal as _signal

__implements__ = []
__extensions__ = []
_child_handler = _INITIAL
_signal_signal = _signal.signal
_signal_getsignal = _signal.getsignal


def getsignal(signalnum):
    """
    Exactly the same as :func:`signal.signal` except where
    :const:`signal.SIGCHLD` is concerned.
    
    For :const:`signal.SIGCHLD`, this cooperates with :func:`signal`
    to provide consistent answers.
    """
    global _child_handler
    if signalnum != _signal.SIGCHLD:
        return _signal_getsignal(signalnum)
    else:
        if _child_handler is _INITIAL:
            _child_handler = _signal_getsignal(_signal.SIGCHLD)
        return _child_handler


def signal(signalnum, handler):
    """
    Exactly the same as :func:`signal.signal` except where
    :const:`signal.SIGCHLD` is concerned.
    
    .. note::
    
       A :const:`signal.SIGCHLD` handler installed with this function
       will only be triggered for children that are forked using
       :func:`gevent.os.fork` (:func:`gevent.os.fork_and_watch`);
       children forked before monkey patching, or otherwise by the raw
       :func:`os.fork`, will not trigger the handler installed by this
       function. (It's unlikely that a SIGCHLD handler installed with
       the builtin :func:`signal.signal` would be triggered either;
       libev typically overwrites such a handler at the C level. At
       the very least, it's full of race conditions.)
    
    .. note::
    
        Use of ``SIG_IGN`` and ``SIG_DFL`` may also have race conditions
        with libev child watchers and the :mod:`gevent.subprocess` module.
    
    .. versionchanged:: 1.2a1
         If ``SIG_IGN`` or ``SIG_DFL`` are used to ignore ``SIGCHLD``, a
         future use of ``gevent.subprocess`` and libev child watchers
         will once again work. However, on Python 2, use of ``os.popen``
         will fail.
    
    .. versionchanged:: 1.1rc2
         Allow using ``SIG_IGN`` and ``SIG_DFL`` to reset and ignore ``SIGCHLD``.
         However, this allows the possibility of a race condition if ``gevent.subprocess``
         had already been used.
    """
    global _child_handler
    if signalnum != _signal.SIGCHLD:
        return _signal_signal(signalnum, handler)
    else:
        if handler != _signal.SIG_IGN:
            if handler != _signal.SIG_DFL:
                if not callable(handler):
                    raise TypeError(
                        "signal handler must be signal.SIG_IGN, signal.SIG_DFL, or a callable object"
                    )
        old_handler = getsignal(signalnum)
        _child_handler = handler
        if handler == _signal.SIG_IGN or handler == _signal.SIG_DFL:
            from gevent import get_hub

            _signal_signal(signalnum, handler)
            get_hub().loop.reset_sigchld()
        return old_handler


def _on_child_hook():
    if callable(_child_handler):
        from gevent import Greenlet

        greenlet = Greenlet(_child_handler, _signal.SIGCHLD, None)
        greenlet.switch()


import gevent.os

if "waitpid" in gevent.os.__implements__:
    if hasattr(_signal, "SIGCHLD"):
        gevent.os._on_child_hook = _on_child_hook
        __implements__.append("signal")
        __implements__.append("getsignal")
    __extensions__.append("signal")
    __extensions__.append("getsignal")
__imports__ = copy_globals(
    _signal,
    globals(),
    names_to_ignore=__implements__ + __extensions__,
    dunder_names_to_keep=(),
)
__all__ = __implements__ + __extensions__
